#if defined(_MSC_VER)
#pragma once
#endif

#ifndef LM_CORE_VECTOR2_H
#define LM_CORE_VECTOR2_H

#include "lm.h"

class Vector2
{
public:
	Vector2() : x(0), y(0) { }
	Vector2(float val) : x(val), y(val) { }
	Vector2(float vx, float vy) : x(vx), y(vy) {}
	explicit Vector2(const Point2 &p);
#ifndef NDEBUG
	Vector2(const Vector2 &v) : x(v.x), y(v.y) {
		Assert(!HasNaNs());
	}
	Vector2 &operator=(const Vector2 &v) {
		x = v.x; y = v.y;
		Assert(!HasNaNs());
		return *this;
	}
#endif
	Point2 operator+(const Point2 &p) const ;
	Vector2 operator+(const Vector2 &v) const {
		Assert(!HasNaNs());
		return Vector2(x+v.x, y+v.y);
	}
	Vector2 &operator+=(const Vector2 &v) {
		Assert(!HasNaNs());
		x += v.x; y += v.y;
		return *this;
	}
	Vector2 operator-(const Vector2 &v) const {
		Assert(!HasNaNs());
		return Vector2(x-v.x, y-v.y);
	}
	Vector2 &operator-=(const Vector2 &v) {
		Assert(!HasNaNs());
		x -= v.x; y -= v.y; 
		return *this;
	}
	Vector2 operator*(float f) const {
		Assert(!HasNaNs());
		return Vector2(x*f, y*f);
	}
	Vector2 &operator*=(float f) {
		Assert(!HasNaNs());
		x *= f; y *= f;
		return *this;
	}
	Vector2 operator/(float f) const {
		Assert(!HasNaNs());
		if(f == 0)
			Warning("Division by 0 in file %s, line %d\n",__FILE__,__LINE__);
		float invf = (float)1 / f;
		return Vector2(x*invf, y*invf);
	}
	Vector2 &operator/=(float f) {
		Assert(!HasNaNs());
		if(f == 0)
			Warning("Division by 0 in file %s, line %d\n",__FILE__,__LINE__);
		float invf = (float)1 / f;
		x *= invf; y *= invf;
		return *this;
	}
	Vector2 operator-() const {
		return Vector2(-x, -y);
	}
	bool operator==(const Vector2 &v) const {
		return x == v.x && y == v.y;
	}
	bool operator!=(const Vector2 &v) const {
		return !(*this == v);
	}
	float operator[](int i) const {
		Assert(i >= 0 && i <= 1);
		return (&x)[i];
	}
	float &operator[](int i) {
		Assert(i >=0 && i <= 1);
		return (&x)[i];
	}
	float LengthSqured() const {
		return x*x + y*y;
	}
	float Length() const {
		return sqrtf(x*x + y*y);
	}
	bool IsZero() const {
		return x == 0 && y == 0;
	}
	bool HasNaNs() const {
		return isnan(x) || isnan(y);
	}
	// Return a readable string representation of this vector
	std::string ToString() const {
		std::ostringstream oss;
		oss << "Vector2 " << "[" << x << ", " << y << "]";
		return oss.str();
	}
	float x, y;
};

#endif	// LM_CORE_VECTOR2_H